package com.cskaoyan.pointcut;


import com.cskaoyan.bean.pojo.Logout;
import com.cskaoyan.bean.pojo.LogoutExample;
import com.cskaoyan.bean.pojo.admin.Admin;
import com.cskaoyan.dao.LogoutMapper;
import lombok.Data;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.Serializable;
import java.util.LinkedList;
import java.util.List;

/**
 * 定义一个类叫切面类 👉 注册到容器中
 * 提供通知
 */

/**
 * @author: lds
 * @class:  CustomAspect
 */
//@Aspect
//@Component
//@Data
public class CustomAspect {
    /**
     * 修饰符：public/private
     * 返回值：void
     * 方法名：任意写·->方法名作为切入点id
     * 形参：没有参数
     * 方法体：没有内容
     */
    @Pointcut("execution(* com..backgroundsystemcontroller..*(..) )"/*写入切入点表达式*/)
    public void myPointcut(){
        System.out.println(111);
    }

    /**
     * value可以直接写切入点表达式-->相当于pointcut属性
     * value也可以引入切入点方法-->pointcut-ref
     */
     //@Before("execution(* com..service..*(..))")
    @Before("myPointcut()"/*如果通过切入点方法进行指定，后面有一对括号*/)
    public void methodBefore() {

//        System.out.println(1111);
//        Object[] args = joinPoint.getArgs();
//        System.out.println(args);
//        System.out.println("before通知的方法");
    }
     @After("myPointcut()")
    public void methodAfter() {
        try {
            kickout();
        }catch (Exception e) {
            return;
        }

         //System.out.println("after通知的方法");
    }




    @Autowired
    LogoutMapper loginMapper;

    //返回值为Object，参数中包含ProceedingJoinPoint
    @Around("myPointcut()")
    public Object methodAround(ProceedingJoinPoint joinPoint/*joinPoint传入连接点*/) throws Throwable { //环绕通知 👉 需要有一行代码 👉 委托类方法的执行

        //System.out.println("around通知的方法：前半部分");
        Signature signature = joinPoint.getSignature();
        String name = signature.getName();
        System.err.println("方法名为："+name);
        Object proceed = null;
        kickoutaround(name);
        System.out.println("before");
        try {

                proceed = joinPoint.proceed();//执行的是委托类的方法

            }catch (Throwable e) {
                e.printStackTrace();
                System.out.println("抛出异常");
            }
        kickoutaround2(name);
//        System.out.println("after");
        //System.out.println("around通知的方法：后半部分");
        return proceed;
    }

    private void kickoutaround(String name) {
        if (!(name.equals("authLogin") || name.equals("loginByEmail") || name.equals("authLogout") || name.equals("logoutKickout"))) {

            kickout();//判断是否需要踢出并踢出
        }
    }
    private void kickoutaround2(String name) {
        if (!(name.equals("authLogin") || name.equals("loginByEmail") || name.equals("authLogout") )) {

            if ((name.equals("logoutKickout")))
            {
                return;
            }
            kickout();//判断是否需要踢出并踢出
        }
    }

    private void kickout() {
        LogoutExample logoutExample = new LogoutExample();
        LogoutExample.Criteria criteria = logoutExample.createCriteria();
        criteria.andDeletedEqualTo(false);
        List<Logout> logouts = loginMapper.selectByExample(logoutExample);
        if (logouts.size() > 0) {
            Subject subject = SecurityUtils.getSubject();
            Serializable id = subject.getSession().getId();
            if (id ==null){
                return;
            }

//            Admin primaryPrincipal = (Admin) subject.getPrincipals().getPrimaryPrincipal();
//            System.out.println(primaryPrincipal.getId());
//            String username = primaryPrincipal.getUsername();
//            String password = primaryPrincipal.getPassword();

            LinkedList<String> strings = new LinkedList<>();
            for (Logout logout : logouts) {
                strings.add(logout.getToken());
            }
            if (strings.contains(id.toString()))
            {

                subject.logout();
                LogoutExample logoutExample1 = new LogoutExample();
                LogoutExample.Criteria criteria1 = logoutExample1.createCriteria();
                criteria1.andTokenEqualTo(id.toString());
                Logout logout = new Logout();
                logout.setDeleted(true);
                int i = loginMapper.updateByExampleSelective(logout, logoutExample1);
                System.out.println("是否删除了token"+i);

            }
        }

    }

    //AfterReturning通知 👉 委托类方法的执行结果，可以直接放在形参中
    //                  👉形参名可以任意写，但是需要指定
//    @AfterReturning(value = "myPointcut()",returning = "result")
//    public void methodAfterReturning(Object result){
//        //System.out.println("AfterReturning通知：" + result);
//    }

    //AfterThrowing通知
    //通过Exception或Throwable类型的形参来接收委托类方法抛出的异常
//    @AfterThrowing(value = "myPointcut()",throwing = "exception")
//    public void methodAfterThrowing(Exception exception){
//        //exception.printStackTrace();
////        System.out.println("AfterThrowing通知的方法：" + exception.getMessage());
//        //System.out.println("AfterThrowing通知的方法：" + exception.getMessage());
//    }
}
